package com.tudulist.security;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.wicket.authroles.authentication.AuthenticatedWebSession;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.injection.Injector;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.RememberMeServices;

@SuppressWarnings("serial")
public class UserAuthenticatedWebSession extends AuthenticatedWebSession {

	private static Logger logger = Logger.getLogger(UserAuthenticatedWebSession.class);

	@SpringBean(name = "authenticationManager")
	AuthenticationManager authenticationManager;

	@SpringBean(name = "rememberMeServices")
	RememberMeServices rememberMeServices;

	private Boolean rememberMe;

	public UserAuthenticatedWebSession(Request request) {
		super(request);
		Injector.get().inject(this);
	}

	@Override
	public boolean authenticate(String username, String password) {
		try {
			Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
			if (auth.isAuthenticated()) {
				SecurityContextHolder.getContext().setAuthentication(auth);

				if (rememberMe) {
					HttpServletRequest servletRequest = (HttpServletRequest) RequestCycle.get().getRequest().getContainerRequest();
					HttpServletResponse servletResponse = (HttpServletResponse) RequestCycle.get().getResponse().getContainerResponse();
					rememberMeServices.loginSuccess(servletRequest, servletResponse, auth);
				}

				return true;
			} else {
				return false;
			}
		} catch (BadCredentialsException bad) {
			logger.warn("Failed login attempt due to exception!", bad);
			return false;
		} catch (AuthenticationException e) {
			logger.warn("Failed login attempt due to exception!", e);
			return false;
		}
	}

	@Override
	public Roles getRoles() {
		Roles roles = new Roles();
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		if (authentication != null) {
			for (GrantedAuthority authority : authentication.getAuthorities()) {
				roles.add(authority.getAuthority());
			}
		}
		return roles;
	}

	public boolean signIn(String username, String password, Boolean rememberMe) {
		this.rememberMe = rememberMe;
		return super.signIn(username, password);
	}

}
